// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraQuickBarComponent.h"

#include "Equipment/LyraEquipmentDefinition.h"
#include "Equipment/LyraEquipmentInstance.h"
#include "Equipment/LyraEquipmentManagerComponent.h"
#include "GameFramework/GameplayMessageSubsystem.h"
#include "GameFramework/Pawn.h"
#include "Inventory/InventoryFragment_EquippableItem.h"
#include "NativeGameplayTags.h"
#include "Net/UnrealNetwork.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraQuickBarComponent)

class FLifetimeProperty;
class ULyraEquipmentDefinition;

UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Lyra_QuickBar_Message_SlotsChanged, "Lyra.QuickBar.Message.SlotsChanged"); // 定义槽位更改游戏玩法标签
UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Lyra_QuickBar_Message_ActiveIndexChanged, "Lyra.QuickBar.Message.ActiveIndexChanged"); // 定义活动索引更改游戏玩法标签

/**
 * 构造函数
 * @param ObjectInitializer - 对象初始化器
 */
ULyraQuickBarComponent::ULyraQuickBarComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	SetIsReplicatedByDefault(true); // 默认启用复制
}

/**
 * 注册生命周期复制属性
 * @param OutLifetimeProps - 输出生命周期属性数组
 */
void ULyraQuickBarComponent::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps); // 调用父类方法

	DOREPLIFETIME(ThisClass, Slots); // 复制 Slots
	DOREPLIFETIME(ThisClass, ActiveSlotIndex); // 复制 ActiveSlotIndex
}

/**
 * 开始游戏
 */
void ULyraQuickBarComponent::BeginPlay()
{
	if (Slots.Num() < NumSlots) // 检查槽位数量不足
	{
		Slots.AddDefaulted(NumSlots - Slots.Num()); // 添加默认槽位
	}

	Super::BeginPlay(); // 调用父类方法
}

/**
 * 向前循环活动槽位
 */
void ULyraQuickBarComponent::CycleActiveSlotForward()
{
	if (Slots.Num() < 2) // 检查槽位数量不足
	{
		return;
	}

	const int32 OldIndex = (ActiveSlotIndex < 0 ? Slots.Num()-1 : ActiveSlotIndex); // 计算旧索引
	int32 NewIndex = ActiveSlotIndex; // 新索引
	do
	{
		NewIndex = (NewIndex + 1) % Slots.Num(); // 计算下一个索引
		if (Slots[NewIndex] != nullptr) // 检查槽位不为空
		{
			SetActiveSlotIndex(NewIndex); // 设置活动槽位索引
			return;
		}
	} while (NewIndex != OldIndex); // 循环直到回到起点
}

/**
 * 向后循环活动槽位
 */
void ULyraQuickBarComponent::CycleActiveSlotBackward()
{
	if (Slots.Num() < 2) // 检查槽位数量不足
	{
		return;
	}

	const int32 OldIndex = (ActiveSlotIndex < 0 ? Slots.Num()-1 : ActiveSlotIndex); // 计算旧索引
	int32 NewIndex = ActiveSlotIndex; // 新索引
	do
	{
		NewIndex = (NewIndex - 1 + Slots.Num()) % Slots.Num(); // 计算上一个索引
		if (Slots[NewIndex] != nullptr) // 检查槽位不为空
		{
			SetActiveSlotIndex(NewIndex); // 设置活动槽位索引
			return;
		}
	} while (NewIndex != OldIndex); // 循环直到回到起点
}

/**
 * 装备槽位中的物品
 */
void ULyraQuickBarComponent::EquipItemInSlot()
{
	check(Slots.IsValidIndex(ActiveSlotIndex)); // 检查活动槽位索引有效
	check(EquippedItem == nullptr); // 检查未装备物品

	if (ULyraInventoryItemInstance* SlotItem = Slots[ActiveSlotIndex]) // 获取槽位物品
	{
		if (const UInventoryFragment_EquippableItem* EquipInfo = SlotItem->FindFragmentByClass<UInventoryFragment_EquippableItem>()) // 查找可装备物品片段
		{
			TSubclassOf<ULyraEquipmentDefinition> EquipDef = EquipInfo->EquipmentDefinition; // 获取装备定义
			if (EquipDef != nullptr) // 检查装备定义有效
			{
				if (ULyraEquipmentManagerComponent* EquipmentManager = FindEquipmentManager()) // 查找装备管理器
				{
					EquippedItem = EquipmentManager->EquipItem(EquipDef); // 装备物品
					if (EquippedItem != nullptr) // 检查装备成功
					{
						EquippedItem->SetInstigator(SlotItem); // 设置发起者
					}
				}
			}
		}
	}
}

/**
 * 卸下槽位中的物品
 */
void ULyraQuickBarComponent::UnequipItemInSlot()
{
	if (ULyraEquipmentManagerComponent* EquipmentManager = FindEquipmentManager()) // 查找装备管理器
	{
		if (EquippedItem != nullptr) // 检查有装备物品
		{
			EquipmentManager->UnequipItem(EquippedItem); // 卸下物品
			EquippedItem = nullptr; // 清空已装备物品
		}
	}
}

/**
 * 查找装备管理器
 * @return 装备管理器组件
 */
ULyraEquipmentManagerComponent* ULyraQuickBarComponent::FindEquipmentManager() const
{
	if (AController* OwnerController = Cast<AController>(GetOwner())) // 获取所有者控制器
	{
		if (APawn* Pawn = OwnerController->GetPawn()) // 获取控制器所属 Pawn
		{
			return Pawn->FindComponentByClass<ULyraEquipmentManagerComponent>(); // 查找装备管理器组件
		}
	}
	return nullptr; // 未找到返回空
}

/**
 * 设置活动槽位索引（服务器实现）
 * @param NewIndex - 新索引
 */
void ULyraQuickBarComponent::SetActiveSlotIndex_Implementation(int32 NewIndex)
{
	if (Slots.IsValidIndex(NewIndex) && (ActiveSlotIndex != NewIndex)) // 检查新索引有效且不同
	{
		UnequipItemInSlot(); // 卸下当前物品

		ActiveSlotIndex = NewIndex; // 设置新索引

		EquipItemInSlot(); // 装备新物品

		OnRep_ActiveSlotIndex(); // 调用复制通知
	}
}

/**
 * 获取活动槽位物品
 * @return 活动槽位物品实例
 */
ULyraInventoryItemInstance* ULyraQuickBarComponent::GetActiveSlotItem() const
{
	return Slots.IsValidIndex(ActiveSlotIndex) ? Slots[ActiveSlotIndex] : nullptr; // 返回活动槽位物品或空
}

/**
 * 获取下一个空闲物品槽位
 * @return 空闲槽位索引
 */
int32 ULyraQuickBarComponent::GetNextFreeItemSlot() const
{
	int32 SlotIndex = 0; // 槽位索引
	for (const TObjectPtr<ULyraInventoryItemInstance>& ItemPtr : Slots) // 遍历槽位
	{
		if (ItemPtr == nullptr) // 检查槽位为空
		{
			return SlotIndex; // 返回空闲索引
		}
		++SlotIndex; // 递增索引
	}

	return INDEX_NONE; // 无空闲槽位返回无效索引
}

/**
 * 添加物品到槽位
 * @param SlotIndex - 槽位索引
 * @param Item - 物品实例
 */
void ULyraQuickBarComponent::AddItemToSlot(int32 SlotIndex, ULyraInventoryItemInstance* Item)
{
	if (Slots.IsValidIndex(SlotIndex) && (Item != nullptr)) // 检查槽位索引有效且物品不为空
	{
		if (Slots[SlotIndex] == nullptr) // 检查槽位为空
		{
			Slots[SlotIndex] = Item; // 设置槽位物品
			OnRep_Slots(); // 调用复制通知
		}
	}
}

/**
 * 从槽位移除物品
 * @param SlotIndex - 槽位索引
 * @return 被移除的物品实例
 */
ULyraInventoryItemInstance* ULyraQuickBarComponent::RemoveItemFromSlot(int32 SlotIndex)
{
	ULyraInventoryItemInstance* Result = nullptr; // 结果

	if (ActiveSlotIndex == SlotIndex) // 检查活动槽位匹配
	{
		UnequipItemInSlot(); // 卸下物品
		ActiveSlotIndex = -1; // 重置活动索引
	}

	if (Slots.IsValidIndex(SlotIndex)) // 检查槽位索引有效
	{
		Result = Slots[SlotIndex]; // 获取结果

		if (Result != nullptr) // 检查结果有效
		{
			Slots[SlotIndex] = nullptr; // 清空槽位
			OnRep_Slots(); // 调用复制通知
		}
	}

	return Result; // 返回结果
}

/**
 * 复制通知：槽位
 */
void ULyraQuickBarComponent::OnRep_Slots()
{
	FLyraQuickBarSlotsChangedMessage Message; // 创建消息
	Message.Owner = GetOwner(); // 设置所有者
	Message.Slots = Slots; // 设置槽位

	UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(this); // 获取消息子系统
	MessageSystem.BroadcastMessage(TAG_Lyra_QuickBar_Message_SlotsChanged, Message); // 广播消息
}

/**
 * 复制通知：活动槽位索引
 */
void ULyraQuickBarComponent::OnRep_ActiveSlotIndex()
{
	FLyraQuickBarActiveIndexChangedMessage Message; // 创建消息
	Message.Owner = GetOwner(); // 设置所有者
	Message.ActiveIndex = ActiveSlotIndex; // 设置活动索引

	UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(this); // 获取消息子系统
	MessageSystem.BroadcastMessage(TAG_Lyra_QuickBar_Message_ActiveIndexChanged, Message); // 广播消息
}